package main

import (
	"log"
	"net/http"

	"gopkg.in/go-oauth2/redis.v3"
	"gopkg.in/oauth2.v3/errors"
	"gopkg.in/oauth2.v3/manage"
	"gopkg.in/oauth2.v3/models"
	"gopkg.in/oauth2.v3/server"
	"gopkg.in/oauth2.v3/store"
	"time"
	"gopkg.in/oauth2.v3"
	"gopkg.in/oauth2.v3/generates"
	"github.com/dgrijalva/jwt-go"
)

func main() {
	manager := manage.NewDefaultManager()
	//设置授权码过期时间（默认为10分钟）
	manager.SetAuthorizeCodeExp(time.Minute * 20)

	//设置授权码模式令牌的配置参数
	cfg := &manage.Config{
		// 访问令牌过期时间（默认为2小时）
		AccessTokenExp: time.Hour * 2,
		// 更新令牌过期时间（默认为72小时）
		RefreshTokenExp: time.Hour * 24 * 3,
		// 是否生成更新令牌
		IsGenerateRefresh: true,
	}
	manager.SetAuthorizeCodeTokenCfg(cfg)

	//设置简化模式令牌的配置参数
	implCfg := &manage.Config{
		// 访问令牌过期时间（默认为1小时）
		AccessTokenExp: time.Hour * 1,
	}
	manager.SetImplicitTokenCfg(implCfg)

	//设置密码模式令牌的配置参数
	passCfg := &manage.Config{
		// 访问令牌过期时间（默认为2小时）
		AccessTokenExp: time.Hour * 2,
		// 更新令牌过期时间（默认为7天）
		RefreshTokenExp: time.Hour * 24 * 7,
		// 是否生成更新令牌
		IsGenerateRefresh: true,
	}
	manager.SetPasswordTokenCfg(passCfg)

	clientCfg := &manage.Config{
		// 访问令牌过期时间（默认为2小时）
		AccessTokenExp: time.Hour * 2,
		// 更新令牌过期时间（默认为7天）
		RefreshTokenExp: time.Hour * 24 * 7,
		// 是否生成更新令牌
		IsGenerateRefresh: true,
	}
	manager.SetClientTokenCfg(clientCfg)

	//设置更新令牌的配置参数
	refreshCfg := &manage.RefreshingConfig{
		// 是否重新生成更新令牌
		IsGenerateRefresh: true,
		IsRemoveAccess:true,

	}
	manager.SetRefreshTokenCfg(refreshCfg)


	// token memory store
	//manager.MustTokenStorage(store.NewMemoryTokenStore())
	manager.MapTokenStorage(redis.NewRedisStore(&redis.Options{
		Addr: "127.0.0.1:6379",
		DB: 15,
	}))

	manager.MapAccessGenerate(generates.NewJWTAccessGenerate([]byte("zppvae"),jwt.SigningMethodHS512))

	// client memory store
	clientStore := store.NewClientStore()
	clientStore.Set("000000", &models.Client{
		ID:     "000000",
		Secret: "999999",
		Domain: "http://localhost",
	})
	manager.MapClientStorage(clientStore)

	srv := server.NewDefaultServer(manager)
	srv.SetAllowGetAccessRequest(true)
	srv.SetClientInfoHandler(server.ClientFormHandler)
	srv.SetAllowedGrantType(oauth2.AuthorizationCode,oauth2.PasswordCredentials,oauth2.ClientCredentials)


	srv.SetInternalErrorHandler(func(err error) (re *errors.Response) {
		log.Println("Internal Error:", err.Error())
		return
	})

	srv.SetResponseErrorHandler(func(re *errors.Response) {
		log.Println("Response Error:", re.Error.Error())
	})

	http.HandleFunc("/authorize", func(w http.ResponseWriter, r *http.Request) {
		err := srv.HandleAuthorizeRequest(w, r)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
		}
	})

	http.HandleFunc("/oauth/token", func(w http.ResponseWriter, r *http.Request) {
		srv.HandleTokenRequest(w, r)
	})

	log.Fatal(http.ListenAndServe(":9096", nil))
}